﻿#pragma once
#ifndef Session_hpp
#define Session_hpp

#include<string>
#include<memory>
#include<functional>
#include<atomic>
#include<vector>
#include<boost/asio.hpp>
#include<boost/system/detail/error_code.hpp>
#include"./NetworkDef.hpp"

namespace MMFNetwork
{
    using namespace boost::asio;

    //前置声明，用于定义后面的回调函数
    class Session;      

    using SessionConnectHandler = std::function<void(const std::shared_ptr<Session>& session)>;                                     ///< 客户端链接session
    using SessionErrorHandler = std::function<void(const std::shared_ptr<Session>& session, boost::system::error_code err)>;        ///< 错误处理回调函数
    using SessionStatusHandler = std::function<void(const std::shared_ptr<Session>& session, Status status)>;                       ///< 状态处理回调函数
    using SessionAsyncHandler = std::function<void(void* buffer, bool state)>;                                                      ///< 异步收发回调函数
    using SessionPackageHandler = std::function<void(const std::shared_ptr<Session>& session, void* pkg, size_t size)>;             ///< 数据包处理回调函数       

    //服务前置声明
    class Server;

    class Session: public std::enable_shared_from_this<Session>     //本类在使用时需要配合只能指针
    {

        io_context& mService;                   ///< session所属的service
        ip::tcp::socket mSocket;                ///< 套接字

        const uint32_t mBufferSize;             ///< 用于接收的缓存大小
        std::vector<void*> mRecvBuffers;        ///< 接收缓存，小黄缓冲一个用于接收，一个用于处理数据
        uint8_t mCurrentBuff;                   ///< 当前使用的是第几块buff，块数只能为2
        uint32_t mCurrentRecvBytes;             ///< 当前接收的字节数

        std::string mLocalIp;                   ///< 本地IP              
        std::string mRemoteIp;                  ///< 远端IP
        uint16_t mLocalPort, mRemotePort;       ///< 端口
        MMFNetwork::Status mStatus;             ///< 现在状态

        SessionErrorHandler mErrorHandler;             ///< 错误处理
        SessionStatusHandler mStatusHandler;           ///< 状态处理
        SessionPackageHandler mPkgHandler;             ///< 数据包处理

        //声明服务类为友元
        friend class Server;

    public:

        Session(
            io_context& service,
            uint32_t bufferSize,
            const SessionErrorHandler& errorHandler,
            const SessionStatusHandler& statusHandler,
            const SessionPackageHandler& pkgHandler,
            MMFInetFamily family
        );

        ~Session();

        void Start();
        void Stop(MMFNetwork::Status status = MMFNetwork::Status::Invalid);

        const std::string& LocalIp();
        const std::string& RemoteIp();

        uint16_t LocalPort();
        uint16_t RemotePort();

        Status CurrentStatus();

        bool Send(void* buff, uint32_t count);
        bool Recv(void* buff, uint32_t count);

        //发送数据的时候是确定的知道数据要发送多少的
        //可以直接通过回调知道发送完毕即可，甚至不出错的情况下，都不需要知道结果
        void AsyncSend(void* buff, uint32_t count);

        //接收预定字节数的数据，
        //除非明确知道数据大小
        void AsyncRecv(void* buff, uint32_t count, const SessionAsyncHandler& handler);

        //接收数据包
        //通过数据包通过回调进行通知
        //收完一个数据包会继续收下一个数据包
        void AsyncRecvPackage();
    };

}


#endif